
#ifndef _CONFIG__CONFIG_IMPL_H__INCLUDED_
#define _CONFIG__CONFIG_IMPL_H__INCLUDED_

#include "Config.h"

#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

#ifndef ISVW_INTEGRATION
	#define ENABLE_DEBUG_LOG
#endif

#ifdef ENABLE_DEBUG_LOG
	#include "Logger.h"
	#define CFG_MODULE                     "Config"
	#define CFG_VERBOSE                    CFG_MODULE, nebula::sdk::LOG_LEVEL_VERBOSE
	#define CFG_INFO                       CFG_MODULE, nebula::sdk::LOG_LEVEL_INFORMATION
	#define CFG_ERROR                      CFG_MODULE, nebula::sdk::LOG_LEVEL_ERROR
#else
	#define CFG_VERBOSE                    0
	#define CFG_INFO                       0
	#define CFG_ERROR                      0
	#undef LOG
	#define LOG fake_log
	static inline void fake_log(...) {}
#endif

namespace smartvoice {

/////////////////////////////////////////////////////////////////////////////

class ValueNodeImpl: public ValueNode
{
private:
	const string m_name;
	string       m_value;

public:
	virtual const char* GetName() const
	{
		return m_name.c_str();
	}

	virtual const char* GetValue() const
	{
		return m_value.c_str();
	}

	virtual void SetValue(const char* value)
	{
		m_value = value;
	}

	virtual void SetValue(unsigned int value)
	{
		ostringstream oss;
		oss << value;
		m_value = oss.str();
	}

public:
	ValueNodeImpl(const char* name):
		m_name(name)
	{
	}
	ValueNodeImpl* Clone() const
	{
		ValueNodeImpl* cloned = new ValueNodeImpl(GetName());
		if (0 == cloned)
			return 0;
		cloned->SetValue(GetValue());
		return cloned;
	}
};

/////////////////////////////////////////////////////////////////////////////

class KeyNodeImpl: public KeyNode
{
private:
	string      m_name;
	KeyNodeList m_subkeys;
	ValueList   m_values;

public:
	virtual ~KeyNodeImpl()
	{
		Clear();
	}
	virtual const char* GetName() const
	{
		return m_name.c_str();
	}
	virtual KeyNodeList& GetSubkeys()
	{
		return m_subkeys;
	}
	virtual const KeyNodeList& GetSubkeys() const
	{
		return m_subkeys;
	}
	virtual KeyNode* GetSubkey(const char* name)
	{
		return get_deep_subkey(name);
	}
	virtual const KeyNode* GetSubkey(const char* name) const
	{
		return get_deep_subkey(name);
	}
	virtual ValueList& GetValues()
	{
		return m_values;
	}
	virtual const ValueList& GetValues() const
	{
		return m_values;
	}
	virtual const char* GetValue(const char* name) const
	{
		const ValueNode* value = get_deep_value(name);
		if (0 == value)
			return 0;
		return value->GetValue();
	}
	virtual KeyNode* AppendSubkey(const char* name)
	{
		return append_deep_subkey(name);
	}
	virtual KeyNode* AppendSubkey(const KeyNode* subtree)
	{
		KeyNode *new_node = subtree->Clone();
		m_subkeys.push_back(new_node);
		return new_node;
	}
	virtual KeyNode* SpliceSubkey(KeyNode* subkey)
	{
		m_subkeys.push_back(subkey);
		return subkey;
	}
	virtual bool RemoveSubkey(const char* name)
	{
		KeyNode *subkey = ReleaseSubkey(name);
		if (subkey == 0)
			return false;

		delete subkey;
		return true;
	}
	virtual bool RemoveSubkey(KeyNode* subkey_)
	{
		KeyNode *subkey = ReleaseSubkey(subkey_);
		if (subkey == 0)
			return false;

		delete subkey;
		return true;
	}
	virtual KeyNode* ReleaseSubkey(const char* name)
	{
		for (KeyNodeList::iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
			if (0 == strcmp((*iter)->GetName(), name))
			{
				KeyNode* subkey = *iter;
				m_subkeys.erase(iter);
				return subkey;
			}
		return 0;
	}
	virtual KeyNode* ReleaseSubkey(KeyNode* subkey)
	{
		for (KeyNodeList::iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
			if (*iter == subkey)
			{
				m_subkeys.erase(iter);
				return subkey;
			}
		return 0;
	}
	virtual void SetValue(const char* name, const char* value)
	{
		get_direct_value(name, true)->SetValue(value);
	}
	virtual void SetValue(const char* name, unsigned int value)
	{
		get_direct_value(name, true)->SetValue(value);
	}
	virtual void AppendValue(const char* name, const char* value)
	{
		m_values.push_back(static_cast<ValueNode*>(new ValueNodeImpl(name)));
		m_values.back()->SetValue(value);
	}
	virtual void AppendValue(const char* name, unsigned int value)
	{
		m_values.push_back(static_cast<ValueNode*>(new ValueNodeImpl(name)));
		m_values.back()->SetValue(value);
	}
	virtual bool RemoveValue(const char* name)
	{
		for (ValueList::iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
			if (0 == strcmp((*iter)->GetName(), name))
			{
				delete *iter;
				m_values.erase(iter);
				return true;
			}
		return false;
	}
	virtual KeyNode* Clone() const
	{
		KeyNodeImpl* cloned = new KeyNodeImpl(GetName());
		if (0 == cloned)
			return 0;

		for (ValueList::const_iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
		{
			ValueNodeImpl* value = (dynamic_cast<ValueNodeImpl*>(*iter))->Clone();
			if (0 == value)
			{
				delete cloned;
				return 0;
			}
			cloned->m_values.push_back(value);
		}
		for (KeyNodeList::const_iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
		{
			KeyNode* subkey = (*iter)->Clone();
			if (0 == subkey)
			{
				delete subkey;
				return 0;
			}
			cloned->m_subkeys.push_back(subkey);
		}
		return cloned;
	}

public:
	KeyNodeImpl(const char* name=0)
	{
		SetName(name);
	}
	void SetName(const char* name)
	{
		if (0 != name)
			m_name = name;
	}
	void Dump() const
	{
		Dump(0);
		LOG(CFG_INFO, "--END--");
	}
	void Clear()
	{
		for (KeyNodeList::iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
			delete *iter;
		m_subkeys.clear();
		for (ValueList::iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
			delete *iter;
		m_values.clear();
	}
	bool SaveToMemory(std::string &memory) const
	{
		ostringstream mout;
		if (!mout)
			return false;
		if (!SaveToOStream(mout))
			return false;

		memory = mout.str();
		return true;
	}
	bool SaveToFile(const char* file) const
	{
		ofstream fout(file);
		if (!fout)
			return false;

		bool succeed = SaveToOStream(fout);
		fout.close();
		return succeed;
	}

public:
	// implemented in ConfigImpl.xerces.cpp / ConfigImpl.libxml.cpp
	bool LoadFromMemory(const char* config);
	bool LoadFromFile(const char* file);
	bool SaveToOStream(ostream &os) const;

protected:
	KeyNode* get_deep_subkey(const char* name) const
	{
		if (name == 0 || name[0] == '\0')
			return 0;

		vector<string> names;
		split_path(names, name);

		return get_deep_subkey(names.begin(), names.end());
	}
	template <typename iterator>
	KeyNode* get_deep_subkey(iterator key_name_begin, iterator key_name_end) const
	{
		const string &name = *key_name_begin;
		iterator key_name_next = key_name_begin + 1;
		for (KeyNodeList::const_iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
		{
			if ((*iter)->GetName() == name)
			{
				if (key_name_next == key_name_end)
					return *iter;
				else
				{
					KeyNode* subkey = (dynamic_cast<KeyNodeImpl*>(*iter))->
								get_deep_subkey(key_name_next, key_name_end);
					if (0 != subkey)
						return subkey;
				}
			}
		}
		return 0;
	}
	ValueNode* get_deep_value(const char* name) const
	{
		if (name == 0 || name[0] == '\0')
			return 0;

		vector<string> names;
		split_path(names, name);

		if (names.size() == 0)
			return 0;
		if (names.size() == 1)
			return get_direct_value(names[0].c_str());

		return get_deep_value(names.begin(), names.end()-1, names.back().c_str());
	}
	template <typename iterator>
	ValueNode* get_deep_value(
			iterator key_name_begin, iterator key_name_end, const char* value_name) const
	{
		const string &name = *key_name_begin;
		iterator key_name_next = key_name_begin + 1;
		for (KeyNodeList::const_iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
		{
			if ((*iter)->GetName() == name)
			{
				if (key_name_next == key_name_end)
				{
					ValueNode* value = (dynamic_cast<KeyNodeImpl*>(*iter))->
								get_direct_value(value_name);
					if (0 != value)
						return value;
				}
				else
				{
					ValueNode* value = (dynamic_cast<KeyNodeImpl*>(*iter))->
								get_deep_value(key_name_next, key_name_end, value_name);
					if (0 != value)
						return value;
				}
			}
		}
		return 0;
	}
	ValueNode* get_direct_value(const char* name) const
	{
		for (ValueList::const_iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
			if (0 == strcmp((*iter)->GetName(), name))
				return *iter;
		return 0;
	}
	ValueNode* get_direct_value(const char* name, bool add_if_not_exist)
	{
		for (ValueList::iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
			if (0 == strcmp((*iter)->GetName(), name))
				return *iter;

		if (!add_if_not_exist)
			return 0;

		m_values.push_back(static_cast<ValueNode*>(new ValueNodeImpl(name)));
		return m_values.back();
	}
	KeyNode* append_deep_subkey(const char* name)
	{
		if (name == 0 || name[0] == '\0')
			return 0;

		vector<string> names;
		split_path(names, name);

		if (names.size() == 0)
			return 0;
		if (names.size() == 1)
			return append_direct_subkey(names[0].c_str());

		return append_deep_subkey(names.begin(), names.end()-1, names.back().c_str());
	}
	template <typename iterator>
	KeyNode* append_deep_subkey(iterator key_name_begin, iterator key_name_end, const char* subkey_name)
	{
		const string &direct_subkey_name = *key_name_begin;
		iterator key_name_next = key_name_begin + 1;
		KeyNode *direct_subkey = 0;
		for (KeyNodeList::const_iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
		{
			if ((*iter)->GetName() == direct_subkey_name)
			{
				direct_subkey = *iter;
				break;
			}
		}

		if (direct_subkey == 0)
		{
			direct_subkey = append_direct_subkey(direct_subkey_name.c_str());
			if (direct_subkey == 0)
				return 0;
		}

		if (key_name_next == key_name_end)
		{
			return (dynamic_cast<KeyNodeImpl*>(direct_subkey))->
						append_direct_subkey(subkey_name);
		}
		else
		{
			return (dynamic_cast<KeyNodeImpl*>(direct_subkey))->
						append_deep_subkey(key_name_next, key_name_end, subkey_name);
		}
	}
	KeyNode* append_direct_subkey(const char* subkey_name)
	{
		KeyNodeImpl *new_node = new KeyNodeImpl(subkey_name);
		if (0 != new_node)
			m_subkeys.push_back(new_node);
		return new_node;
	}
	void Dump(int depth) const
	{
		std::string indent;
		{	ostringstream oss;
			for (int d=0; d<depth; ++d)
				oss << "   ";
			indent = oss.str();
		}
		LOG(CFG_INFO, "%s%s", indent.c_str(), GetName());

		for (ValueList::const_iterator iter = m_values.begin(); iter != m_values.end(); ++iter)
		{
			ValueNode *value = *iter;
			LOG(CFG_INFO, "%s   %s = %s", indent.c_str(), value->GetName(), value->GetValue());
		}
		for (KeyNodeList::const_iterator iter = m_subkeys.begin(); iter != m_subkeys.end(); ++iter)
			(dynamic_cast<KeyNodeImpl*>(*iter))->Dump(depth+1);
	}
	static void split_path(vector<string> &names, const char* name)
	{
		string s(name);
		for (string::iterator i=s.begin(); i!=s.end(); ++i)
		{
			if (*i == '\\')
				*i = '/';
		}

//		sk::split(names, s, '/');
		{
			std::istringstream iss(s);
			for( std::string sub; std::getline(iss, sub, '/'); )
				names.push_back(sub);
		}
	}
};

} // end namespace smartvoice

#endif // _CONFIG__CONFIG_IMPL_H__INCLUDED_

